#include <gtest/gtest.h>
#include <chrono>
#include "viml/parser.h"
#include "viml/ast_detailed_printer.h"
#include "viml/ast_printer.h"

namespace viml {

class ASTDetailedPrinterTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 准备测试数据
    }
    
    void TearDown() override {
        // 清理
    }
};

// 测试基本的AST详细输出功能
TEST_F(ASTDetailedPrinterTest, BasicDetailedOutput) {
    std::string source = "let x = 42";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证输出包含期望的内容
    EXPECT_TRUE(output.find("Program") != std::string::npos);
    EXPECT_TRUE(output.find("LetStatement") != std::string::npos);
    EXPECT_TRUE(output.find("NumberLiteral") != std::string::npos);
    EXPECT_TRUE(output.find("节点类型") != std::string::npos);
    EXPECT_TRUE(output.find("节点ID") != std::string::npos);
    EXPECT_TRUE(output.find("层级深度") != std::string::npos);
}

// 测试复杂表达式的AST输出
TEST_F(ASTDetailedPrinterTest, ComplexExpressionOutput) {
    std::string source = "let result = 1 + 2 * 3";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证二元表达式的详细信息
    EXPECT_TRUE(output.find("BinaryExpression") != std::string::npos);
    EXPECT_TRUE(output.find("运算符") != std::string::npos);
    EXPECT_TRUE(output.find("左操作数") != std::string::npos);
    EXPECT_TRUE(output.find("右操作数") != std::string::npos);
    EXPECT_TRUE(output.find("表达式类型: Number") != std::string::npos);
    EXPECT_TRUE(output.find("常量表达式") != std::string::npos);
}

// 测试函数定义的AST输出
TEST_F(ASTDetailedPrinterTest, FunctionDefinitionOutput) {
    std::string source = "function add(a, b)\n  return a + b\nendfunction";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证函数定义的详细信息
    EXPECT_TRUE(output.find("FunctionStatement") != std::string::npos);
    EXPECT_TRUE(output.find("函数名: add") != std::string::npos);
    EXPECT_TRUE(output.find("参数数量: 2") != std::string::npos);
    EXPECT_TRUE(output.find("ReturnStatement") != std::string::npos);
    EXPECT_TRUE(output.find("函数体") != std::string::npos);
}

// 测试类型推断功能
TEST_F(ASTDetailedPrinterTest, TypeInferenceTest) {
    std::string source = "let name = \"hello\"";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    config.show_types = true;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证字符串类型推断
    EXPECT_TRUE(output.find("StringLiteral") != std::string::npos);
    EXPECT_TRUE(output.find("表达式类型: String") != std::string::npos);
    EXPECT_TRUE(output.find("常量表达式") != std::string::npos);
}

// 测试内存使用分析
TEST_F(ASTDetailedPrinterTest, MemoryAnalysisTest) {
    std::string source = "let data = [1, 2, 3]";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    config.show_memory = true;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证内存使用信息
    EXPECT_TRUE(output.find("ListLiteral") != std::string::npos);
    EXPECT_TRUE(output.find("内存占用") != std::string::npos);
    EXPECT_TRUE(output.find("bytes") != std::string::npos);
}

// 测试复杂度分析
TEST_F(ASTDetailedPrinterTest, ComplexityAnalysisTest) {
    std::string source = "if x > 0\n  echo \"positive\"\nelse\n  echo \"negative\"\nendif";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证复杂度分析
    EXPECT_TRUE(output.find("IfStatement") != std::string::npos);
    EXPECT_TRUE(output.find("复杂度评分") != std::string::npos);
    EXPECT_TRUE(output.find("then分支") != std::string::npos);
    EXPECT_TRUE(output.find("else分支") != std::string::npos);
}

// 测试配置选项功能
TEST_F(ASTDetailedPrinterTest, ConfigurationOptionsTest) {
    std::string source = "let x = 42";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    // 测试禁用内存显示
    viml::DetailedOutputConfig config;
    config.show_memory = false;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证内存信息不显示
    EXPECT_TRUE(output.find("内存占用") == std::string::npos);
}

// 测试嵌套结构的递归显示
TEST_F(ASTDetailedPrinterTest, NestedStructureTest) {
    std::string source = "let nested = {\"key\": [1, 2, {\"inner\": \"value\"}]}";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证嵌套结构的正确显示
    EXPECT_TRUE(output.find("DictLiteral") != std::string::npos);
    EXPECT_TRUE(output.find("ListLiteral") != std::string::npos);
    EXPECT_TRUE(output.find("键值对") != std::string::npos);
    EXPECT_TRUE(output.find("元素") != std::string::npos);
    EXPECT_TRUE(output.find("子节点递归展示") != std::string::npos);
}

// 测试符号引用分析
TEST_F(ASTDetailedPrinterTest, SymbolReferenceTest) {
    std::string source = "let x = 10\nlet y = x + 5";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    viml::DetailedOutputConfig config;
    config.show_symbol_references = true;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    // 验证符号引用分析
    EXPECT_TRUE(output.find("Identifier") != std::string::npos);
    EXPECT_TRUE(output.find("符号引用") != std::string::npos);
    EXPECT_TRUE(output.find("local_variable") != std::string::npos);
}

// 测试输出与现有AST Pretty Printer的兼容性
TEST_F(ASTDetailedPrinterTest, CompatibilityWithExistingPrinter) {
    std::string source = "echo \"Hello, World!\"";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    // 使用现有的Pretty Printer
    viml::ASTPrettyPrinter pretty_printer;
    program->accept(pretty_printer);
    std::string pretty_output = pretty_printer.get_output();
    
    // 使用新的详细Printer
    viml::DetailedOutputConfig config;
    viml::ASTDetailedPrinter detailed_printer(config);
    detailed_printer.set_source_code(source);
    program->accept(detailed_printer);
    std::string detailed_output = detailed_printer.get_detailed_output();
    
    // 两种输出都应该包含基本的AST节点信息
    EXPECT_TRUE(pretty_output.find("EchoStatement") != std::string::npos);
    EXPECT_TRUE(pretty_output.find("StringLiteral") != std::string::npos);
    
    EXPECT_TRUE(detailed_output.find("EchoStatement") != std::string::npos);
    EXPECT_TRUE(detailed_output.find("StringLiteral") != std::string::npos);
    
    // 详细输出应该包含更多信息
    EXPECT_TRUE(detailed_output.length() > pretty_output.length());
    EXPECT_TRUE(detailed_output.find("节点ID") != std::string::npos);
    EXPECT_TRUE(detailed_output.find("复杂度评分") != std::string::npos);
}

// 性能测试 - 确保详细输出不会显著影响性能
TEST_F(ASTDetailedPrinterTest, PerformanceTest) {
    // 创建一个相对复杂的VimL代码
    std::string source = R"(
        function fibonacci(n)
            if n <= 1
                return n
            else
                return fibonacci(n-1) + fibonacci(n-2)
            endif
        endfunction
        
        let result = fibonacci(10)
        echo result
    )";
    
    viml::Parser parser(source);
    auto program = parser.parse();
    
    auto start = std::chrono::high_resolution_clock::now();
    
    viml::DetailedOutputConfig config;
    viml::ASTDetailedPrinter printer(config);
    printer.set_source_code(source);
    program->accept(printer);
    std::string output = printer.get_detailed_output();
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 确保处理时间在合理范围内（小于100毫秒）
    EXPECT_LT(duration.count(), 100);
    EXPECT_FALSE(output.empty());
}

} // namespace viml